시작하기
선언적 렌더링(Declarative Rendering)방식으로 시작하기
지후아빠
12-15 15:55
요약
- 선언적 렌더링은 Vue.js를 이용해 프론트엔드를 간단히 구성하는 방법입니다.
- 빠른 프로토타입 제작에 유용하며, 학습 및 테스트 환경에서 적합합니다.
- H:Dev+ 샘플 코드를 활용하여 직접 구현하고 실행해볼 수 있습니다.
선언적 렌더링(Declarative Rendering)
'선언적 렌더링(Declarative Rendering)'은 HTML에 출력될 요소를 직접 선언하는 방식입니다. Vue.js 공식 문서에서는 아래와 같은 방식을 선언적 렌더링으로 설명하고 있습니다.
JS 예제 코드
import { createApp } from 'vue' createApp({ data() { return { count: 0 } } }).mount('#app')
Template
<div id="app"> <button @click="count++"> Count is: {{ count }} </button> </div>
H:Dev+와 선언적 렌더링
H:Dev+**를 가장 빠르게 경험할 수 있는 방법은 선언적 렌더링 방식을 이용해 프론트엔드를 구현하는 것입니다.
선언적 렌더링의 활용 대상- Vue.js로 프론트엔드 개발을 학습하는 사용자
- 빠른 프로토타입을 구현하려는 중소기업 또는 에이전시
선언적 렌더링 방식은 보안적 위험(예: SECORE_KEY
노출) 및 기능 제한이 있을 수 있으므로 프로덕션 환경에서는 권장되지 않습니다.그러나, 빠른 프로토타입 제작에는 매우 유용합니다.
H:Dev+ 콘솔에서 SECORE_KEY
를 재 설정 할 수 있습니다..
샘플 코드
Git Repositorygit clone https://github.com/zmania/HDevPlus-example.git디렉터리 구조
nuxt3 php spring-boot vue-dr vue
vue-dr
디렉터리에는 선언적 렌더링 방식으로 작성된 Vue.js 코드가 포함되어 있습니다.
vue-dr
디렉터리의 index.html 파일을 크롬 또는 엣지 브라우저에서 열면 실제로 H:Dev+와 연동된 페이지를 확인할 수 있습니다.
선언적 렌더링 샘플 코드
HTML 페이지 상단에 데이터를 요청하는 스크립트(<!--Request Data -->영역)를 정의하고, 페이지 내부에서 Vue.js의 데이터 바인딩 기능을 사용하여 데이터를 출력합니다.
코드 예시<!doctype html> <html lang="en" data-bs-theme="auto"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content=""> <meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors"> <meta name="generator" content="Hugo 0.111.3"> <title>H:Dev+ Sample Code</title> <!-- BOOTSTRAP OPTIONAL --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous"><!-- REQUEST DATA --> <script> const requestData = {'dataID': 'GET_POST_LIST', 'list_per_page': 2, 'page_link_url':'list.html','search_keyword': new URLSearchParams(window.location.search).get('search_keyword'), 'page': new URLSearchParams(window.location.search).get('page') ? new URLSearchParams(window.location.search).get('page') : 1}; </script><style> [v-cloak] { display: none; } </style> </head> <body> <div id="app" v-cloak> <gnb-comp :output="output"></gnb-comp> <div class="container"> <main> <div class="row g-5"> <div class="col-12"> <div class="text-center"> <h2 class="mt-5 mb-3">게시물 목록</h2> </div> <div class="py-2 d-flex justify-content-between align-items-center"> <small class="smaller text-black"> Result {{output.pagination.total_result_num}} post / total {{output.total_post_count}} post </small> <a :href="output.user.auth_flg ? './add.html' : '../member/login.html'" class="btn btn-sm btn-dark d-flex justify-content-between align-items-center lh-1"><small class="smaller">ADD</small></a> </div> <div id="post_list" data-load-type="vue-pagination" class="row h-post-list"> <div class="col-12 my-3" v-if="output.post_list.length>0" v-for="post in output.post_list"> <div class="card h-100"> <div class="card-body"> <div class="d-flex justify-content-between align-items-center"> <small>{{post.reg_name}}</small><small>{{post.create_date}}</small> </div> <hr/> <h1 class="fs-3 card-title py-3"><a :href="'./view.html?post_key='+post.post_key" v-html="post.subject"></a></h1> <p class="card-text" v-html="post.content"></p> </div> </div> </div> <div class="col-12" v-else> <div class="my-2 d-flex justify-content-center align-items-center alert alert-light"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-bell" viewBox="0 0 16 16"> <path d="M8 16a2 2 0 0 0 2-2H6a2 2 0 0 0 2 2zM8 1.918l-.797.161A4.002 4.002 0 0 0 4 6c0 .628-.134 2.197-.459 3.742-.16.767-.376 1.566-.663 2.258h10.244c-.287-.692-.502-1.49-.663-2.258C12.134 8.197 12 6.628 12 6a4.002 4.002 0 0 0-3.203-3.92L8 1.917zM14.22 12c.223.447.481.801.78 1H1c.299-.199.557-.553.78-1C2.68 10.2 3 6.88 3 6c0-2.42 1.72-4.44 4.005-4.901a1 1 0 1 1 1.99 0A5.002 5.002 0 0 1 13 6c0 .88.32 4.2 1.22 6z"/> </svg> <span class="ms-2">게시물이 없습니다.</span> </div> </div> </div> </div> </div> </main> <bottom :output="output"></bottom> </div> </div> <!-- JQUERY REQUIRED --> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.form/4.3.0/jquery.form.min.js"></script> <!-- VUE --> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.2.47/vue.global.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue-router/4.1.6/vue-router.global.js"></script> <!-- BOOTSTRAP OPTIONAL --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe" crossorigin="anonymous"></script><!-- CONNECTOR --> <script src="../_connector/yellow.501.js"></script><script src="../components/gnb.js"></script> <script src="../components/bottom.js"></script> </body> </html>
명령형 렌더링(Imperative Rendering)
위에서 작성한 선언적 렌더링 방식은 이후 명령형 렌더링 방식으로 확장해도 활용이 용이합니다. 명령형 렌더링의 예제는 vue
디렉터리에서 확인할 수 있습니다.